
package com.seekting.study;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

public class SocketChannelTest {

    public static void main(String[] args) {
        server();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        client();
    }

    private static void server() {
        try {
            final ServerSocketChannel socketChannel = ServerSocketChannel.open();
            socketChannel.configureBlocking(false);
            final ServerSocket socket = socketChannel.socket();
            socket.bind(new InetSocketAddress(5200));
            final Selector selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_ACCEPT);
            new Thread(new Runnable() {

                @Override
                public void run() {

                    while (true) {
                        try {
                            selector.select();
                            Set<SelectionKey> kes = selector.selectedKeys();
                            SocketChannel sc = null;
                            Iterator<SelectionKey> i = kes.iterator();
                            while (i.hasNext()) {
                                SelectionKey key = i.next();
                                if (key.isAcceptable()) {
                                    SocketChannel client = ((ServerSocketChannel) key.channel())
                                            .accept();
                                    System.out.println("Accept connection from: " + client);
                                    client.configureBlocking(false);
                                    client.register(key.selector(), SelectionKey.OP_READ,
                                            ByteBuffer.allocate(1024));

                                } else if (key.isReadable()) {

                                    // 获得与客户端通信的信道
                                    SocketChannel clientChannel = (SocketChannel) key.channel();

                                    // 得到并清空缓冲区
                                    ByteBuffer buffer = (ByteBuffer) key.attachment();
                                    buffer.clear();

                                    // 读取信息获得读取的字节数
                                    long bytesRead = clientChannel.read(buffer);

                                    if (bytesRead == -1) {
                                        // 没有读取到内容的情况
                                        clientChannel.close();
                                    } else {
                                        // 将缓冲区准备为数据传出状态
                                        buffer.flip();

                                        // 将字节转化为为UTF-16的字符串
                                        String receivedString = Charset.forName("UTF-16")
                                                .newDecoder().decode(buffer).toString();

                                        // 控制台打印出来
                                        System.out.println("接收到来自"
                                                + clientChannel.socket().getRemoteSocketAddress()
                                                + "的信息:" + receivedString);

                                        // 准备发送的文本
                                        String sendString = "你好,客户端. @" + new Date().toString()
                                                + "，已经收到你的信息" + receivedString;
                                        buffer = ByteBuffer.wrap(sendString.getBytes("UTF-16"));
                                        clientChannel.write(buffer);

                                        // 设置为下一次读取或是写入做准备
                                        key.interestOps(SelectionKey.OP_READ
                                                | SelectionKey.OP_WRITE);
                                    }
                                }
                                if (key.isWritable())
                                {
                                    SocketChannel ssc = (SocketChannel) key.channel();
                                    ByteBuffer writeBuffer = ByteBuffer.wrap("我的程序员之道"
                                            .getBytes("UTF-16"));
                                    ssc.write(writeBuffer);
                                }
                                key.channel().close();

                                i.remove();

                            }

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private static void client() {
        try {
            final SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            final Socket socket = socketChannel.socket();
            InetAddress ia = InetAddress.getLocalHost();
            InetSocketAddress isa = new InetSocketAddress(ia, 5200);
            socketChannel.connect(isa);
            socketChannel.configureBlocking(false);
            System.out.println("与服务器的连接建立成功");
            final Selector selector = Selector.open();
            new Thread(new Runnable() {

                @Override
                public void run() {
                    Exception e = null;
                    try {

                        socketChannel.register(selector, SelectionKey.OP_READ
                                | SelectionKey.OP_WRITE);
                        while (true) {
                            selector.select();
                            Set keySet = selector.selectedKeys();
                            Iterator iter = keySet.iterator();
                            while (iter.hasNext()) {
                                SelectionKey key = (SelectionKey) iter.next();
                                iter.remove();

                                if (key.isReadable()) {
                                    System.out.println("客户端可读...");
                                }
                                if (key.isWritable()) {
                                    System.out.println("客户端可写...");
                                }
                            }

                        }
                    } catch (Exception e1) {
                        e = e1;
                        e.printStackTrace();
                        System.out.println(e);
                    } finally {
                        System.out.println("rr" + e);
                    }

                }
            }).start();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
